# coding:utf-8
import ctypes
import glob
import hashlib
import multiprocessing
import os.path
import shutil
import sys
import threading
import time
import uuid
from functools import partial
from multiprocessing import Queue
from queue import Empty

import requests
import win32com

from PySide2.QtCore import Qt, QCoreApplication, QTimer
from PySide2.QtGui import QIcon, QPixmap, QFont
from PySide2.QtNetwork import QLocalServer, QLocalSocket
from PySide2.QtWidgets import QPushButton, QHBoxLayout, QVBoxLayout
from qfluentwidgets import InfoBar, InfoBarPosition, FluentIcon, Dialog, setThemeColor, setCustomStyleSheet, Theme, \
    FluentTranslator

import ChatBot
from interface import progress_dialog
import ui_friend_list
import dialog_config
import dialog_advanced_config
from interface.chat_window import ChatWindow
from common.log import logger, logger_1
from config import load_config, conf, initialize_config_if_missing, check_config
from dialog_config import ConfigDialog
from LogWindow import ShowLogWindow, trim_log_file
from interface.progress_dialog import ProgressDialog
from ui_friend_list import FriendListView
from interface.window_main_chat import *
from interface.search_friend_messagebox import SearchFriendMessageBox
import winshell
from win32com.client import Dispatch
import resource_rc

from qss import *
from version_information import VERSION, NAME, FILE_NAME, CURRENT_VERSION_NUMBER

requests.packages.urllib3.disable_warnings()

logged_in = [False] * 2  # 登录状态的标志，True为已登录，False为离线
processes_list = [False] * 2  # 进程是否正在运行的标志，True为正在运行，False为已停止


class SingleInstance(QApplication):
    def __init__(self, key, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._key = key
        self._server = QLocalServer(self)
        self._server.newConnection.connect(self.handle_connection)

        if self.is_running():
            # 已有实例在运行，发送信号并退出
            self.send_show_window_signal()
            sys.exit(0)  # 退出当前实例
        else:
            self._server.listen(key)

    def is_running(self):
        # 检查是否有其他实例在运行
        socket = QLocalSocket(self)
        socket.connectToServer(self._key)
        if socket.waitForConnected(1000):
            socket.disconnectFromServer()
            return True
        return False

    def send_show_window_signal(self):
        # 发送信号给已有实例
        socket = QLocalSocket(self)
        socket.connectToServer(self._key)
        if socket.waitForConnected(1000):
            socket.write(b'UserCareSystem')
            socket.waitForBytesWritten(1000)
            socket.disconnectFromServer()

    def handle_connection(self):
        socket = self._server.nextPendingConnection()
        if socket.waitForReadyRead(1000):
            data = socket.readAll().data()
            if data == b'UserCareSystem':
                self.show_main_window()
        socket.disconnectFromServer()

    def show_main_window(self):
        # 显示主窗口
        for widget in self.topLevelWidgets():
            if isinstance(widget, MainWindow):
                if widget.isMinimized():
                    widget.showNormal()  # 恢复窗口到正常状态
                elif widget.isHidden():
                    widget.show()  # 如果窗口被隐藏，显示窗口
                widget.activateWindow()  # 激活窗口
                widget.raise_()  # 将窗口置顶
                break


class QRcodeCheckThread(QThread):
    """
    检测二维码是否生成的线程
    """
    check_signal = Signal(int)

    def __init__(self, index, parent=None):
        super().__init__(parent)
        self.index = index
        self.running = True

    def run(self):
        while self.running:
            self.check_signal.emit(self.index)
            self.sleep(1)

    def stop_thread(self):
        self.running = False


class QueueReader(QThread):
    """
    使用Queue进行进程间的消息通讯,处理队列读取的线程
    """
    # 登录出错的信号
    signal_login_error = Signal(str)
    # 是否登陆成功的信号
    signal_login = Signal(int)
    # 显示用户昵称的信号
    signal_name = Signal(int, str)
    # 是否手动登出或掉线的信号
    signal_logout = Signal(int, str)
    # 好友列表同步数量
    signal_friends_num = Signal(int, tuple)
    # 接收到好友列表
    signal_friend_list = Signal(int, list)
    # 接收到消息
    signal_message_list = Signal(int, list)
    # 接收单条消息数据
    signal_message_data = Signal(int, dict)
    # 接受登录用户的数据
    signal_my_info = Signal(int, dict)
    # 提示微信实名的信号
    signal_real_name_certification = Signal(int)
    # 搜索到目标好友的信号
    signal_search_friend = Signal(int, tuple)

    def __init__(self, queue):
        super().__init__()
        self.queue = queue
        # self.running = False

    def run(self):
        while True:
            try:
                data = self.queue.get()
                index, type, content = data
                if type == "STATUS":
                    if content == "SUCCESS":
                        self.signal_login.emit(index)
                    elif content == "LOGOUT":
                        self.signal_logout.emit(index, "LOGOUT")
                    elif content == "FAIL":
                        self.signal_real_name_certification.emit(index)
                elif type == "LogError":
                    self.signal_login_error.emit(content)
                elif type == "NAME":
                    self.signal_name.emit(index, content)
                elif type == "MyInfo":
                    self.signal_my_info.emit(index, content)
                elif type == "FriendsNum":
                    self.signal_friends_num.emit(index, content)
                elif type == "FriendData":
                    self.signal_friend_list.emit(index, content)
                elif type == "Message":
                    self.signal_message_list.emit(index, content)
                elif type == "MessageData":
                    self.signal_message_data.emit(index, content)
                elif type == "SearchFriend":
                    self.signal_search_friend.emit(index, content)
                else:
                    # 如果都不符合条件，则把数据放回self.queue
                    self.queue.put(data)
            except Empty:
                pass
            time.sleep(1)


class BotRunProcess:
    def __init__(self):
        self.run_process_1 = None
        self.run_process_2 = None

    def start_process(self, queue_1, queue_2, queue_3, index):
        load_config()
        process_name = f"run_process_{index}"
        process = getattr(self, process_name, None)
        if process is not None:
            try:
                process.terminate()
                process.join()
            except AttributeError as e:
                pass
            except Exception as e:
                logger.error(f"终止进程时发生错误: {e}")
        if process is None:
            process = ChatBot.WeChatBot(queue_1, queue_2, queue_3, index)
            process.daemon = True
            setattr(self, process_name, process)
        process.start()

    def stop_process(self, queue_2, index, status=0):
        """
        停止指定的进程，并在队列中放置一个退出信号。

        :param queue_2: 用于通信的队列
        :param index: 进程的索引，用于标识要停止的进程
        :param status: 0表示通过登出退出; 1表示通过关闭程序退出
        """
        try:
            queue_2.put((index, "LOGOUT", None))
            process_name = f"run_process_{index}"
            process = getattr(self, process_name, None)
            if process and process.is_alive():
                if status == 0:
                    process.join(timeout=5)  # 设置5秒超时
                    if process.is_alive():
                        process.terminate()
                        process.join()
                elif status == 1:
                    if logged_in[index - 1]:
                        process.join(timeout=5)  # 设置5秒超时
                        if process.is_alive():
                            process.terminate()
                            process.join()
                        logged_in[index - 1] = False
                    elif not logged_in[index - 1]:
                        process.terminate()
                        process.join(timeout=5)  # 设置5秒超时
                        if process.is_alive():
                            process.kill()  # 强制终止
                            process.join()
                setattr(self, process_name, None)
        except Exception as e:
            logger.error(f"发生错误: {e}")

    def message_send(self, queue_2, index, username, message):
        queue_2.put((index, "MESSAGE", (username, message)))


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_WooXinAI()
        self.ui.setupUi(self)

        self.setWindowFlags(
            Qt.Window | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint)

        self.setupLogUpdater()

        # 设置主题色为微信绿
        setThemeColor("#07C160")

        # 隐藏默认边框
        # self.setWindowFlags(Qt.FramelessWindowHint)
        # 创建关闭和最小化按钮
        close_button = QPushButton(QIcon(":/assets/close_icon.png"), "")
        minimize_button = QPushButton(QIcon(":/assets/minimize_icon.png"), "")
        # 连接信号到槽
        close_button.clicked.connect(self.close)
        minimize_button.clicked.connect(self.showMinimized)
        # 创建布局并添加按钮
        title_bar_layout = QHBoxLayout()
        title_bar_layout.addWidget(minimize_button)
        title_bar_layout.addStretch()  # 使按钮居右
        title_bar_layout.addWidget(close_button)
        # self.addLayout(title_bar_layout)

        # 创建系统托盘图标
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(QIcon(':/assets/icon.ico'))  # 设置托盘图标
        self.tray_icon.setToolTip("用户关爱系统")
        self.tray_icon.setVisible(True)

        # 创建托盘菜单
        tray_menu = QMenu()
        restore_action = QAction("显示", self)
        restore_action.triggered.connect(self.restore_from_tray)
        tray_menu.addAction(restore_action)
        tray_menu.addSeparator()
        quit_action = QAction("退出", self)
        quit_action.triggered.connect(self.close)
        tray_menu.addAction(quit_action)

        # 设置托盘菜单
        self.tray_icon.setContextMenu(tray_menu)

        # 绑定托盘图标的激活事件
        self.tray_icon.activated.connect(self.on_tray_icon_activated)

        # 创建BotRunProcess对象
        self.bot_run_process = BotRunProcess()

        # 创建定时器对象
        self.qrcode_checker_timer_1 = None
        self.qrcode_checker_timer_2 = None

        self.qrcode_image_path = ["./bots/bot1/QR.png", "./bots/bot2/QR.png"]

        title = "{}[{}]".format(NAME, CURRENT_VERSION_NUMBER)
        self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))

        self.setWindowIcon(QIcon(":/assets/icon.ico"))

        self.queue_1 = Queue()  # 子进程向主进程通信,传递  已登录, 昵称信息
        self.queue_2 = Queue()  # 主进程向子进程通信,传递  登出命令, 通过输入框发送的消息
        self.queue_3 = Queue()  # 子进程（微信登录进程）向聊天界面发送头像数据专用

        self.my_info_1 = None
        self.my_info_2 = None

        self.name_1 = None
        self.name_2 = None

        # 为按钮添加事件处理
        # "微信"按钮
        self.ui.toolButton_wechat_1.setIcon(FluentIcon.MESSAGE.icon(Theme.DARK))
        self.ui.toolButton_wechat_2.setIcon(FluentIcon.MESSAGE.icon(Theme.DARK))

        self.ui.toolButton_wechat_1.setText("")
        self.ui.toolButton_wechat_2.setText("")

        setCustomStyleSheet(self.ui.toolButton_wechat_1, wechat_style_sheet, wechat_style_sheet)
        setCustomStyleSheet(self.ui.toolButton_wechat_2, wechat_style_sheet, wechat_style_sheet)

        self.ui.toolButton_wechat_1.setChecked(True)
        self.ui.toolButton_wechat_1.clicked.connect(lambda: self.wechat_button_clicked(1))
        self.ui.toolButton_wechat_2.clicked.connect(lambda: self.wechat_button_clicked(2))

        self.ui.toolButton_wechat_3.hide()
        self.ui.toolButton_wechat_4.hide()
        self.ui.toolButton_wechat_5.hide()

        # "配置"按钮
        font = QFont()
        font.setPointSize(12)
        font.setFamily("微软雅黑")

        self.ui.pushButton_config_1.setFont(font)
        self.ui.pushButton_config_2.setFont(font)

        self.ui.pushButton_config_1.setIcon(FluentIcon.SETTING)
        self.ui.pushButton_config_2.setIcon(FluentIcon.SETTING)

        self.ui.pushButton_config_1.clicked.connect(self.open_config_dialog)
        self.ui.pushButton_config_2.clicked.connect(self.open_config_dialog)

        # 登录按钮
        setCustomStyleSheet(self.ui.pushButton_login_1, login_style_sheet_text, login_style_sheet_text)
        setCustomStyleSheet(self.ui.pushButton_login_2, login_style_sheet_text, login_style_sheet_text)

        font = QFont()
        font.setPointSize(14)
        font.setFamily("微软雅黑")
        self.ui.pushButton_login_1.setFont(font)
        self.ui.pushButton_login_2.setFont(font)

        self.ui.pushButton_login_1.clicked.connect(lambda: self.on_login_button_click(1))
        self.ui.pushButton_login_2.clicked.connect(lambda: self.on_login_button_click(2))

        # "消息日志"按钮
        font = QFont()
        font.setPointSize(12)
        font.setFamily("微软雅黑")

        self.ui.pushButton_logs_1.setFont(font)
        self.ui.pushButton_logs_2.setFont(font)

        self.ui.pushButton_logs_1.setIcon(FluentIcon.DOCUMENT)
        self.ui.pushButton_logs_2.setIcon(FluentIcon.DOCUMENT)

        self.ui.pushButton_logs_1.clicked.connect(lambda: self.ui.stackedWidget_w1.setCurrentIndex(1))
        self.ui.pushButton_logs_2.clicked.connect(lambda: self.ui.stackedWidget_w2.setCurrentIndex(1))

        # 搜索好友按钮
        font = QFont()
        font.setPointSize(12)
        font.setFamily("微软雅黑")
        self.ui.pushButton_search_1.setFont(font)
        self.ui.pushButton_search_1.clicked.connect(lambda: self.open_search_friend_messagebox(1))
        self.ui.pushButton_search_1.hide()
        self.ui.pushButton_search_2.setFont(font)
        self.ui.pushButton_search_2.clicked.connect(lambda: self.open_search_friend_messagebox(2))
        self.ui.pushButton_search_2.hide()

        self.search_friend_messagebox = SearchFriendMessageBox(self)
        self.search_friend_messagebox.hide()

        # 检查更新按钮
        self.ui.toolButton_update.setIcon(FluentIcon.DOWNLOAD.icon(Theme.DARK))
        self.ui.toolButton_update.setText("")
        setCustomStyleSheet(self.ui.toolButton_update, wechat_style_sheet, wechat_style_sheet)
        self.ui.toolButton_update.clicked.connect(lambda: self.check_for_updates())

        # 登录日志按钮
        self.ui.toolButton_login_logout_log.setIcon(FluentIcon.DOWNLOAD.VIEW.icon(Theme.DARK))
        self.ui.toolButton_login_logout_log.setText("")
        setCustomStyleSheet(self.ui.toolButton_login_logout_log, wechat_style_sheet, wechat_style_sheet)
        self.ui.toolButton_login_logout_log.clicked.connect(lambda: self.show_log_window())
        self.friend_lists = {1: [], 2: []}

        self.close = False  # 是否确认关闭应用的标记，默认为False

        InfoBar.warning(
            title='注意',
            content="1.使用本应用时不要开启代理，会无法登录助手\n2.登录助手前请检查微信账号是否已在【支付】处完成【实名认证】\n未认证则不符合微信API要求，无法登录助手",
            orient=Qt.Vertical,
            isClosable=True,
            position=InfoBarPosition.BOTTOM,
            duration=-1,  # 永不消失
            parent=self
        )

        # 聊天窗口字典
        self.chat_windows_1 = {}
        self.chat_windows_2 = {}

        # 检查exe同路径下是否有config.json文件，没有则创建
        initialize_config_if_missing()

        # 检查并删除当前路径下名为“旧版本_*”的exe文件
        self.delete_old_exe_files()

        # 设置开机自启动
        try:
            exe_path = self.get_current_exe_path()
            self.update_shortcut_in_startup(exe_path, FILE_NAME)
        except:
            pass

        self.setFixedSize(self.width(), self.height())

        self.restart_flag = False


    def show_log_window(self):
        try:
            log_file_path = "run.log"
            self.log_window = ShowLogWindow(log_file_path, self)
            self.log_window.show()
        except:
            pass

    def get_current_exe_path(self):
        return os.path.abspath(sys.argv[0])

    def create_shortcut_in_startup(self, exe_path, shortcut_name):
        # 获取启动文件夹的路径
        startup_dir = winshell.startup()

        # 构建快捷方式的完整路径
        shortcut_path = os.path.join(startup_dir, f'{shortcut_name}.lnk')

        # 创建快捷方式
        shell = Dispatch('WScript.Shell')
        shortcut = shell.CreateShortCut(shortcut_path)
        shortcut.Targetpath = exe_path
        shortcut.WorkingDirectory = os.path.dirname(exe_path)
        shortcut.save()

    def update_shortcut_in_startup(self, exe_path, shortcut_name):
        try:
            # 获取启动文件夹的路径
            startup_dir = winshell.startup()

            # 构建快捷方式的完整路径
            shortcut_path = os.path.join(startup_dir, f'{shortcut_name}.lnk')

            if os.path.exists(shortcut_path):
                # 更新快捷方式
                shell = Dispatch('WScript.Shell')
                shortcut = shell.CreateShortCut(shortcut_path)
                shortcut.Targetpath = exe_path
                shortcut.WorkingDirectory = os.path.dirname(exe_path)
                shortcut.save()
                # print("快捷方式已更新")
            else:
                # 创建新的快捷方式
                self.create_shortcut_in_startup(exe_path, shortcut_name)
                # print("快捷方式已创建")
        except:
            pass

    def delete_old_exe_files(self):
        # 匹配所有以"旧版本_"开头的.exe文件
        files_to_delete = glob.glob('旧版本_*.exe')

        # 遍历找到的所有文件
        for file_path in files_to_delete:
            try:
                # 检查文件是否被占用
                if not os.path.exists(file_path) or os.path.getsize(file_path) == 0:
                    continue

                # 尝试删除文件
                os.remove(file_path)
                logger.info(f"已删除: {file_path}")
            except PermissionError:
                logger.error(f"删除失败: {file_path} - 错误: 权限不足")
            except FileNotFoundError:
                logger.error(f"删除失败: {file_path} - 错误: 文件未找到")
            except OSError as e:
                logger.error(f"删除失败: {file_path} - 错误: {e}")

    def show_title_name(self, index):
        index = index + 1
        name = getattr(self, "name_{}".format(index), None)
        if name is not None:
            title = "{}[{}]-当前账号：{}".format(NAME, CURRENT_VERSION_NUMBER, name)
        else:
            title = "{}[{}]".format(NAME, CURRENT_VERSION_NUMBER)
        self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))

    def check_qrcode_exists(self, index):
        """检查二维码图片是否存在并更新UI"""
        if index == 1:
            if os.path.exists(self.qrcode_image_path[index - 1]):
                pixmap = QPixmap(self.qrcode_image_path[index - 1])
                self.ui.qrcode_on_1.setPixmap(pixmap)
                self.ui.qrcode_on_1.setScaledContents(True)  # 让QLabel中的内容根据QLabel大小缩放
                self.ui.qrcode_on_1.setAlignment(Qt.AlignmentFlag.AlignCenter)  # 图片居中显示
                image_size = pixmap.size()
                self.ui.qrcode_on_1.resize(image_size.width(), image_size.height())
            else:
                self.ui.qrcode_on_1.setStyleSheet("background-color:white;")
        elif index == 2:
            if os.path.exists(self.qrcode_image_path[index - 1]):
                pixmap = QPixmap(self.qrcode_image_path[index - 1])
                self.ui.qrcode_on_2.setPixmap(pixmap)
                self.ui.qrcode_on_2.setScaledContents(True)  # 让QLabel中的内容根据QLabel大小缩放
                self.ui.qrcode_on_2.setAlignment(Qt.AlignmentFlag.AlignCenter)  # 图片居中显示
                image_size = pixmap.size()
                self.ui.qrcode_on_2.resize(image_size.width(), image_size.height())
            else:
                self.ui.qrcode_on_2.setStyleSheet("background-color:white;")

    def open_search_friend_messagebox(self, index):
        """
        点击“搜索好友”按钮后，打开此窗口
        """
        try:
            self.search_friend_messagebox.set_index(index, self.queue_1)
            self.search_friend_messagebox.show()
            if self.search_friend_messagebox.exec():
                pass
            else:
                try:
                    pass
                except Exception as e:
                    pass
                    # print(f"An error occurred: {e}")
        except Exception as e:
            pass
            # print(f"An error occurred: {e}")

    def show_the_searched_friend(self, index, userinfo):
        remarkname, nickname, username = userinfo
        if index == 1:
            chat_page = self.chat_windows_1[username]
            # 切换到聊天页面
            self.ui.stackedWidget_w1.setCurrentWidget(chat_page)
            self.search_friend_messagebox.hide()
            show_name = remarkname or nickname
            self.ui.label_friend_name_1.setText("当前聊天：{}".format(show_name))
        elif index == 2:
            chat_page = self.chat_windows_2[username]
            # 切换到聊天页面
            self.ui.stackedWidget_w2.setCurrentWidget(chat_page)
            self.search_friend_messagebox.hide()
            show_name = remarkname or nickname
            self.ui.label_friend_name_2.setText("当前聊天：{}".format(show_name))

    def open_config_dialog(self):
        dialog = ConfigDialog()
        dialog.exec()

    def wechat_button_clicked(self, index):
        if index == 1:
            self.ui.stackedWidget.setCurrentIndex(index - 1)
            self.ui.stackedWidget_w1.setCurrentIndex(0)
            self.show_title_name(index - 1)
            self.ui.toolButton_wechat_2.setChecked(False)
            if not self.ui.toolButton_wechat_1.isChecked():
                self.ui.toolButton_wechat_1.setChecked(True)
        elif index == 2:
            self.ui.stackedWidget.setCurrentIndex(index - 1)
            self.ui.stackedWidget_w2.setCurrentIndex(0)
            self.show_title_name(index - 1)
            self.ui.toolButton_wechat_1.setChecked(False)
            if not self.ui.toolButton_wechat_2.isChecked():
                self.ui.toolButton_wechat_2.setChecked(True)

    def on_login_button_click(self, index):
        """
        登录按钮点击事件
        """

        def check_key_resul_dialog(title, content):
            # 检查key
            _title = title
            _content = content
            msg_box = Dialog(_title, _content)
            msg_box.yesButton.setText("确认")
            msg_box.cancelButton.hide()
            msg_box.buttonLayout.insertStretch(1)
            if msg_box.exec():
                pass
            else:
                pass

        # 检查config.json文件是否存在
        if initialize_config_if_missing():
            pass
        else:
            # 不存在则创建弹出窗口
            InfoBar.warning(
                title='注意',
                content="请点击右上角“配置”填写各项参数",
                orient=Qt.Vertical,
                isClosable=True,
                position=InfoBarPosition.TOP,
                duration=3000,
                parent=self
            )
            return

        # 检查config.json文件必填配置是否填写
        status, content = check_config(index)
        if not status:
            check_key_resul_dialog("配置出错", content)
            return

        if index == 1:
            self.ui.stackedWidget_w1.setCurrentIndex(0)
            if self.ui.pushButton_login_1.text():
                # 初始化 run_process_1
                if self.bot_run_process.run_process_1 is None:
                    load_config()
                    self.bot_run_process.run_process_1 = ChatBot.WeChatBot(self.queue_1, self.queue_2,
                                                                           self.queue_3, index)
                # 检查 key 是否符合要求
                check_key_result = self.bot_run_process.run_process_1.check_key()
                if check_key_result == True:  # 只有在token存在时才启动进程
                    self.ui.pushButton_login_1.setText("")
                    self.on_login(index)
                    # 清理数据库
                    self.delete_local_resources(index)
                else:  # 不存在则显示错误信息
                    # 弹出窗口显示错误信息
                    check_key_resul_dialog("登录出错", check_key_result)
                    self.bot_run_process.run_process_1 = None
                    return
            else:
                logout_message = Dialog("确定登出？", "该账号将登出", self)
                logout_message.yesButton.setText("确认")
                logout_message.cancelButton.setText("取消")
                if logout_message.exec():
                    logout = True
                    # 清理数据库
                    self.delete_local_resources(index)
                else:
                    logout = False
                if logout:
                    self.ui.pushButton_login_1.setIcon(QIcon())
                    self.ui.pushButton_login_1.setIcon(None)
                    self.ui.pushButton_login_1.setText("登录")
                    setCustomStyleSheet(self.ui.pushButton_login_1, login_style_sheet_text, login_style_sheet_text)
                    self.ui.pushButton_login_1.updateGeometry()
                    font = QFont()
                    font.setPointSize(14)
                    font.setFamily("微软雅黑")
                    self.ui.pushButton_login_1.setFont(font)
                    self.on_logout_clicked(index)
                else:
                    pass
        elif index == 2:
            self.ui.stackedWidget_w2.setCurrentIndex(0)
            if self.ui.pushButton_login_2.text():
                # 初始化 run_process_2
                if self.bot_run_process.run_process_2 is None:
                    load_config()
                    self.bot_run_process.run_process_2 = ChatBot.WeChatBot(self.queue_1, self.queue_2,
                                                                           self.queue_3, index)
                # 检查 key 是否符合要求
                check_key_result = self.bot_run_process.run_process_2.check_key()
                if check_key_result == True:  # 只有在token存在时才启动进程
                    self.ui.pushButton_login_2.setText("")
                    self.on_login(index)
                    # 清理数据库
                    self.delete_local_resources(index)
                else:  # 不存在则显示错误信息
                    # 弹出窗口显示错误信息
                    check_key_resul_dialog("登录出错", check_key_result)
                    self.bot_run_process.run_process_2 = None
                    return
            else:
                logout_message = Dialog("确定登出？", "该账号将登出", self)
                logout_message.yesButton.setText("确认")
                logout_message.cancelButton.setText("取消")
                if logout_message.exec():
                    logout = True
                    # 清理数据库
                    self.delete_local_resources(index)
                else:
                    logout = False
                if logout:
                    self.ui.pushButton_login_2.setIcon(QIcon())
                    self.ui.pushButton_login_2.setIcon(None)
                    self.ui.pushButton_login_2.setText("登录")
                    setCustomStyleSheet(self.ui.pushButton_login_2, login_style_sheet_text, login_style_sheet_text)
                    self.ui.pushButton_login_2.updateGeometry()
                    font = QFont()
                    font.setPointSize(14)
                    font.setFamily("微软雅黑")
                    self.ui.pushButton_login_2.setFont(font)
                    self.on_logout_clicked(index)
                else:
                    pass

    def delete_local_resources(self, index):
        # 清理数据库文件
        try:
            file_path = "./bots/bot{}/information.db".format(index)
            if os.path.exists(file_path) and os.path.isfile(file_path):
                try:
                    # 使用os.remove删除文件
                    os.remove(file_path)
                except OSError as e:
                    # logger.error(f"清理数据库出错{e}")
                    pass
            else:
                pass
        except Exception as e:
            pass
        # 清理头像文件
        try:
            file_path = "./bots/bot{}/avatar".format(index)
            if os.path.exists(file_path) and os.path.isdir(file_path):
                try:
                    shutil.rmtree(file_path)
                except OSError as e:
                    # logger.error(f"清理头像出错{e}")
                    pass
            else:
                pass
        except Exception as e:
            pass
        # 清理日志文件
        clear_logs()

    def on_login(self, index):
        """启动按钮事件处理"""
        self.queue_reader = QueueReader(self.queue_1)
        self.queue_reader.daemon = True
        self.queue_reader.signal_login.connect(self.on_login_success)
        self.queue_reader.signal_login_error.connect(self.on_login_error)
        self.queue_reader.signal_name.connect(self.on_show_name)
        self.queue_reader.signal_logout.connect(self.on_show_logout)
        self.queue_reader.signal_real_name_certification.connect(self.show_real_name_window)
        self.queue_reader.signal_my_info.connect(self.update_my_info)
        self.queue_reader.signal_friends_num.connect(self.update_friends_num)
        self.queue_reader.signal_friend_list.connect(self.update_friend_list)
        self.queue_reader.signal_message_data.connect(self.update_message_window)
        self.queue_reader.signal_search_friend.connect(self.show_the_searched_friend)
        self.queue_reader.start()

        if index == 1:
            self.bot_run_process.start_process(self.queue_1, self.queue_2, self.queue_3, 1)
            processes_list[index - 1] = True
            # 检查二维码
            self.qrcode_check_thread = QRcodeCheckThread(index)
            self.qrcode_check_thread.daemon = True
            self.qrcode_check_thread.check_signal.connect(partial(self.check_qrcode_exists))
            self.qrcode_check_thread.start()
            self.ui.pushButton_login_1.setEnabled(False)

        elif index == 2:
            self.bot_run_process.start_process(self.queue_1, self.queue_2, self.queue_3, 2)
            processes_list[index - 1] = True
            # 检查二维码
            self.qrcode_check_thread = QRcodeCheckThread(index)
            self.qrcode_check_thread.daemon = True
            self.qrcode_check_thread.check_signal.connect(partial(self.check_qrcode_exists))
            self.qrcode_check_thread.start()
            self.ui.pushButton_login_2.setEnabled(False)

        time.sleep(3)
        InfoBar.success(
            title='消息',
            content="请扫描二维码登录微信！",
            orient=Qt.Horizontal,
            isClosable=True,
            position=InfoBarPosition.TOP,
            duration=5000,
            parent=self,
        )

    def show_real_name_window(self, index):
        # 创建并显示提示实名的对话框
        _content = "该微信账号未实名认证，请实名认证后或更换账号再试"
        msg_box = Dialog("该账号未实名", _content)
        msg_box.yesButton.setText("确认")
        msg_box.cancelButton.hide()
        msg_box.buttonLayout.insertStretch(1)
        if msg_box.exec():
            pass
        else:
            pass

    def on_login_error(self, content):
        if not self.close:
            self.restart_flag = True
            # 停止所有相关进程
            self.bot_run_process.stop_process(self.queue_2, 1, 1)
            self.bot_run_process.stop_process(self.queue_2, 2, 1)
            # 结束检测二维码的线程
            if self.qrcode_check_thread:
                self.qrcode_check_thread.stop_thread()
            else:
                pass
            # 清理图片缓存
            for index in range(1, 3):
                if os.path.isfile(self.qrcode_image_path[index - 1]):
                    os.remove(self.qrcode_image_path[index - 1])
            _title = "登录出错"
            _content = content + "请重启客户端重新登录"
            msg_box = Dialog(_title, _content)
            msg_box.yesButton.setText("确认")
            msg_box.cancelButton.hide()
            msg_box.buttonLayout.insertStretch(1)
            if msg_box.exec():
                self.restart_application()
            else:
                pass
        else:
            pass

    def close_process(self):
        # 停止所有相关进程
        self.bot_run_process.stop_process(self.queue_2, 1, 1)
        self.bot_run_process.stop_process(self.queue_2, 2, 1)
        # 结束检测二维码的线程
        if self.qrcode_check_thread:
            self.qrcode_check_thread.stop_thread()
        else:
            pass
        # 清理图片缓存
        for index in range(1, 3):
            if os.path.isfile(self.qrcode_image_path[index - 1]):
                os.remove(self.qrcode_image_path[index - 1])

    def on_login_success(self, index):
        """微信登录成功后的事件"""
        global logged_in

        if index == 1:
            logged_in[index - 1] = True
            InfoBar.success(
                title='消息',
                content="登录成功！",
                orient=Qt.Horizontal,
                isClosable=True,
                position=InfoBarPosition.TOP,
                duration=2000,
                parent=self,
            )
            self.ui.qrcode_on_1.setPixmap(QPixmap())
            self.ui.qrcode_on_1.setStyleSheet("background-color: rgb(255, 255, 255);")
            self.ui.qrcode_on_1.setText("同步通讯录中，请耐心等待……")
            # 登录成功后删除二维码图片
            if os.path.isfile(self.qrcode_image_path[index - 1]):
                os.remove(self.qrcode_image_path[index - 1])
            self.ui.pushButton_login_1.setEnabled(True)
            self.ui.pushButton_search_1.show()
            trim_log_file("run.log")
        elif index == 2:
            logged_in[index - 1] = True
            InfoBar.success(
                title='消息',
                content="登录成功！",
                orient=Qt.Horizontal,
                isClosable=True,
                position=InfoBarPosition.TOP,
                duration=2000,
                parent=self,
            )
            self.ui.qrcode_on_2.setPixmap(QPixmap())
            self.ui.qrcode_on_2.setStyleSheet("background-color: rgb(255, 255, 255);")
            self.ui.qrcode_on_2.setText("同步通讯录中，请耐心等待……")
            if os.path.isfile(self.qrcode_image_path[index - 1]):
                os.remove(self.qrcode_image_path[index - 1])
            self.ui.pushButton_login_2.setEnabled(True)
            self.ui.pushButton_search_2.show()
            trim_log_file("run.log")

        # 登录成功后清理检测二维码的线程
        if self.qrcode_check_thread:
            self.qrcode_check_thread.stop_thread()

    def on_show_name(self, index, user_name):
        font = QFont()
        font.setPointSize(11)
        if index == 1:
            self.name_1 = user_name
            title = "{}[{}]-当前账号：{}".format(NAME, CURRENT_VERSION_NUMBER, self.name_1)
            self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))
            self.ui.qrcode_on_1.setText("微信账号 {} 在线".format(self.name_1))
        elif index == 2:
            self.name_2 = user_name
            title = "{}[{}]-当前账号：{}".format(NAME, CURRENT_VERSION_NUMBER, self.name_2)
            self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))
            self.ui.qrcode_on_2.setText("微信账号 {} 在线".format(self.name_2))

    def update_my_info(self, index, my_info):
        font = QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(14)
        if index == 1:
            self.my_info_1 = my_info
            avatar_1 = self.my_info_1["Avatar"]
            # 显示登录用户的头像
            image = QImage()
            image.loadFromData(avatar_1)
            pixmap_1 = QPixmap.fromImage(image)
            setCustomStyleSheet(self.ui.pushButton_login_1, login_style_sheet_icon, login_style_sheet_icon)
            self.ui.pushButton_login_1.setIcon(pixmap_1)
            self.ui.pushButton_login_1.setIconSize(self.ui.pushButton_login_1.size())
            # 显示登录用户的昵称
            self.ui.label_user_name_1.setFont(font)
            self.ui.label_user_name_1.setText(self.my_info_1["NickName"])
        elif index == 2:
            self.my_info_2 = my_info
            avatar_2 = self.my_info_2["Avatar"]
            # 显示登录用户的头像
            image = QImage()
            image.loadFromData(avatar_2)
            pixmap_2 = QPixmap.fromImage(image)
            setCustomStyleSheet(self.ui.pushButton_login_2, login_style_sheet_icon, login_style_sheet_icon)
            self.ui.pushButton_login_2.setIcon(pixmap_2)
            self.ui.pushButton_login_2.setIconSize(self.ui.pushButton_login_2.size())
            self.ui.label_user_name_2.setFont(font)
            self.ui.label_user_name_2.setText(self.my_info_2["NickName"])

    def update_friends_num(self, index, content):
        # 更新显示好友同步的进度
        try:
            if index == 1:
                self.ui.qrcode_on_1.setText("同步通讯录中，请耐心等待……\n同步进度：{}/{}".format(content[0], content[1]))
            elif index == 2:
                self.ui.qrcode_on_2.setText("同步通讯录中，请耐心等待……\n同步进度：{}/{}".format(content[0], content[1]))
        except Exception as e:
            pass

    def update_friend_list(self, index, friend_list):
        # 更新好友列表的显示内容
        if not isinstance(friend_list, list) or not friend_list:
            raise ValueError("friend_list must be a non-empty list")
        # if index not in self.friend_lists:
        #     raise KeyError(f"Index {index} does not exist in self.friend_lists.")
        self.friend_lists[index] = friend_list
        # 更新字典中的好友列表
        if index == 1:
            # 如果已经存在 FriendListView，则更新它的数据源
            if hasattr(self, 'list_view_1'):
                self.list_view_1.model.update_friends_data(friend_list)
                # 初始化好友的聊天窗口
                self.init_chat_windows(index)
            else:
                # 创建新的 FriendListView
                self.list_view_1 = FriendListView(index, self.queue_3, self.queue_2, friends_data=friend_list)
                self.list_view_1.clicked.connect(self.show_chat_window)
                # 清除旧布局
                self.clear_layout(self.ui.friends_list_1)
                # 创建新的布局
                layout_1 = QVBoxLayout()
                layout_1.addWidget(self.list_view_1)
                layout_1.setContentsMargins(0, 0, 0, 0)
                # 设置 frame 的布局为新创建的布局
                self.ui.friends_list_1.setLayout(layout_1)
                # 初始化好友的聊天窗口
                self.init_chat_windows(index)
        elif index == 2:
            # 如果已经存在 FriendListView，则更新它的数据源
            if hasattr(self, 'list_view_2'):
                self.list_view_2.model.update_friends_data(friend_list)
                # 初始化好友的聊天窗口
                self.init_chat_windows(index)
            else:
                # 创建新的 FriendListView
                self.list_view_2 = FriendListView(index, self.queue_3, self.queue_2, friends_data=friend_list)
                self.list_view_2.clicked.connect(self.show_chat_window)
                # 清除旧布局
                self.clear_layout(self.ui.friends_list_2)
                # 创建新的布局
                layout_2 = QVBoxLayout()
                layout_2.addWidget(self.list_view_2)
                layout_2.setContentsMargins(0, 0, 0, 0)
                # 设置 frame 的布局为新创建的布局
                self.ui.friends_list_2.setLayout(layout_2)
                # 初始化好友的聊天窗口
                self.init_chat_windows(index)

    def clear_layout(self, parent):
        """辅助函数：清除给定父窗口的所有子控件和布局"""
        if parent.layout():
            while parent.layout().count():
                child = parent.layout().takeAt(0)
                if child.widget() is not None:
                    child.widget().deleteLater()
                elif child.layout() is not None:
                    self.clear_layout(self, child)  # 递归清除嵌套的布局

    def init_chat_windows(self, index):
        """根据好友数据动态创建和管理聊天窗口"""
        if index == 1:
            friend_model = self.list_view_1.model
            friends_data = friend_model.get_friends_data()
            for i, friend_data in enumerate(friends_data):
                username = friend_data["UserName"]
                if username not in self.chat_windows_1:
                    chat_page = ChatWindow(index, self.my_info_1["UserName"], self.my_info_1["Avatar"], i, friend_data)
                    chat_page.signal_message_send.connect(self.message_send)
                    self.chat_windows_1[username] = chat_page
                    self.ui.stackedWidget_w1.addWidget(chat_page)
        elif index == 2:
            friend_model = self.list_view_2.model
            friends_data = friend_model.get_friends_data()
            for i, friend_data in enumerate(friends_data):
                username = friend_data["UserName"]
                if username not in self.chat_windows_2:
                    chat_page = ChatWindow(index, self.my_info_2["UserName"], self.my_info_2["Avatar"], i, friend_data)
                    chat_page.signal_message_send.connect(self.message_send)
                    self.chat_windows_2[username] = chat_page
                    self.ui.stackedWidget_w2.addWidget(chat_page)

    def show_chat_window(self, index, friend_index):
        """
        点击好友列表中的某好友，显示该好友的聊天框
        """
        if index == 1:
            friend_model = self.list_view_1.model  # 获取模型实例
            friend_data = friend_model.get_friends_data()[friend_index]  # index用于获取特定的好友数据
            username = friend_data["UserName"]
            if username not in self.chat_windows_1:
                chat_page = ChatWindow(index, self.my_info_1["UserName"], self.my_info_1["Avatar"], friend_index,
                                       friend_data)
                # chat_page.signal_message_send.connect(self.message_send)
                self.chat_windows_1[username] = chat_page
                self.ui.stackedWidget_w1.addWidget(chat_page)
            else:
                chat_page = self.chat_windows_1[username]
            # 切换到聊天页面
            self.ui.stackedWidget_w1.setCurrentWidget(chat_page)
            # 有备注显示备注，无备注显示昵称
            show_name = friend_data["RemarkName"] or friend_data["NickName"]
            self.ui.label_friend_name_1.setText("当前聊天：{}".format(show_name))
        elif index == 2:
            friend_model = self.list_view_2.model  # 获取模型实例
            friend_data = friend_model.get_friends_data()[friend_index]  # index用于获取特定的好友数据
            username = friend_data["UserName"]
            if username not in self.chat_windows_2:
                chat_page = ChatWindow(index, self.my_info_2["UserName"], self.my_info_2["Avatar"], friend_index,
                                       friend_data)
                self.chat_windows_2[username] = chat_page
                self.ui.stackedWidget_w2.addWidget(chat_page)
            else:
                chat_page = self.chat_windows_2[username]
            # 切换到聊天页面
            self.ui.stackedWidget_w2.setCurrentWidget(chat_page)
            show_name = friend_data["RemarkName"] or friend_data["NickName"]
            self.ui.label_friend_name_2.setText("当前聊天：{}".format(show_name))

    def update_message_window(self, index, data):
        # 向聊天界面发送信号
        username = data["UserName"]
        if index == 1:
            if username in self.chat_windows_1:
                self.chat_windows_1[username].receive_message(data)
        elif index == 2:
            if username in self.chat_windows_2:
                self.chat_windows_2[username].receive_message(data)

    def message_send(self, index, username, message):
        self.bot_run_process.message_send(self.queue_2, index, username, message)
        # self.queue_2.put((index, "MESSAGE", (username, message)))

    def configure_update_success(self):
        InfoBar.success(
            title='消息',
            content="配置保存成功！",
            orient=Qt.Horizontal,
            isClosable=True,
            position=InfoBarPosition.TOP,
            duration=3000,
            parent=self,
        )

    def on_logout_clicked(self, index):
        """登出按钮事件处理"""
        font = QFont()
        font.setPointSize(22)
        try:
            if index == 1:  # 实际终止逻辑应该在这里实现
                self.logout(index)
                title = "{}[{}]".format(NAME, CURRENT_VERSION_NUMBER)
                self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))
                self.ui.qrcode_on_1.clear()
                self.ui.qrcode_on_1.setStyleSheet("background-color: rgb(255, 255, 255);")
            elif index == 2:
                self.logout(index)
                title = "{}[{}]".format(NAME, CURRENT_VERSION_NUMBER)
                self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))
                self.ui.qrcode_on_2.clear()
                self.ui.qrcode_on_2.setStyleSheet("background-color: rgb(255, 255, 255);")
        except Exception as e:
            logger.error("登出遇到错误：{}".format(e))

    def logout(self, index):
        """处理运行结束后的逻辑"""
        global logged_in
        try:
            if index == 1:
                if self.qrcode_check_thread:
                    self.qrcode_check_thread.stop_thread()
                logged_in[index - 1] = False
                if processes_list[index - 1]:
                    self.bot_run_process.stop_process(self.queue_2, 1)
                    processes_list[index - 1] = False

                InfoBar.success(
                    title='消息',
                    content="已成功登出！",
                    orient=Qt.Horizontal,
                    isClosable=True,
                    position=InfoBarPosition.TOP,
                    duration=3000,
                    parent=self,
                )
                self.name_1 = None
            elif index == 2:
                if self.qrcode_check_thread:
                    self.qrcode_check_thread.stop_thread()
                logged_in[index - 1] = False
                if processes_list[index - 1]:
                    self.bot_run_process.stop_process(self.queue_2, 2)
                    processes_list[index - 1] = False
                InfoBar.success(
                    title='消息',
                    content="已成功登出！",
                    orient=Qt.Horizontal,
                    isClosable=True,
                    position=InfoBarPosition.TOP,
                    duration=3000,
                    parent=self,
                )
                self.name_2 = None
        except Exception as e:
            logger.error("登出遇到错误：{}".format(e))

    def on_show_logout(self, index, info):
        try:
            font = QFont()
            font.setPointSize(22)
            content = "微信账号已 手动登出 或 掉线\n\n如果再次登录失败，请尝试重启客户端"
            title = "{}[{}]".format(NAME, CURRENT_VERSION_NUMBER)
            self.setWindowTitle(QCoreApplication.translate("WooXinAI", title, None))
            trim_log_file("run.log")
            if index == 1:
                if processes_list[index - 1]:  # 处理掉线情况，即非主动登出的情况
                    self.re_start()
                    self.bot_run_process.stop_process(self.queue_2, 1)
                    processes_list[index - 1] = False
                    if not self.ui.pushButton_login_1.text():
                        self.ui.pushButton_login_1.setIcon(QIcon())
                        self.ui.pushButton_login_1.setIcon(None)
                        self.ui.pushButton_login_1.setText("登录")
                        setCustomStyleSheet(self.ui.pushButton_login_1, login_style_sheet_text, login_style_sheet_text)
                        self.ui.pushButton_login_1.updateGeometry()
                        font = QFont()
                        font.setPointSize(10)
                        font.setFamily("微软雅黑")
                        self.ui.pushButton_login_1.setFont(font)
                self.ui.label_user_name_1.setText("")
                self.ui.label_friend_name_1.setText("")
                self.ui.qrcode_on_1.setText(content)
                self.ui.qrcode_on_1.setStyleSheet("color: red;")
                # 清空friend_list组件的内容
                # self.list_view_1.cleanup()
                # self.list_view_1.deleteLater()
                self.list_view_1.model.update_friends_data([])
                self.chat_windows_1 = {}
                # 隐藏搜索好友按钮
                self.ui.pushButton_search_1.hide()
            elif index == 2:
                if processes_list[index - 1]:
                    self.bot_run_process.stop_process(self.queue_2, 2)
                    processes_list[index - 1] = False
                    if not self.ui.pushButton_login_2.text():
                        self.ui.pushButton_login_2.setIcon(QIcon())
                        self.ui.pushButton_login_2.setIcon(None)
                        self.ui.pushButton_login_2.setText("登录")
                        setCustomStyleSheet(self.ui.pushButton_login_2, login_style_sheet_text, login_style_sheet_text)
                        self.ui.pushButton_login_2.updateGeometry()
                        font = QFont()
                        font.setPointSize(10)
                        font.setFamily("微软雅黑")
                        self.ui.pushButton_login_2.setFont(font)
                self.ui.label_user_name_2.setText("")
                self.ui.label_friend_name_2.setText("")
                self.ui.qrcode_on_2.setText(content)
                self.ui.qrcode_on_2.setStyleSheet("color: red;")
                # # 清空friend_list组件的内容
                # self.list_view_2.cleanup()
                # self.list_view_2.deleteLater()
                self.list_view_2.model.update_friends_data([])
                self.chat_windows_2 = {}
                # 隐藏搜索好友按钮
                self.ui.pushButton_search_2.hide()
                if hasattr(self, 'list_view_2'):
                    delattr(self, 'list_view_2')
        except Exception as e:
            logger.error("登出遇到错误：{}".format(e))

        # 清理数据库
        self.delete_local_resources(index)

    def on_tray_icon_activated(self, reason):
        """处理托盘图标的激活事件"""
        if reason == QSystemTrayIcon.DoubleClick:
            self.showNormal()

    def closeEvent(self, event):
        # 创建并显示确认退出的对话框
        self.ui.close_message = Dialog("确定退出？", "所有账号将登出", self)
        self.ui.close_message.adjustSize()
        self.ui.close_message.yesButton.setText("最小化至系统托盘")
        self.ui.close_message.cancelButton.setText("退出程序")

        if self.ui.close_message.exec():
            self.close = False
            # 忽略关闭事件
            event.ignore()
            self.hide()  # 隐藏窗口
            self.tray_icon.show()
        else:
            # 停止所有相关进程
            self.close = True
            self.bot_run_process.stop_process(self.queue_2, 1, 1)
            self.bot_run_process.stop_process(self.queue_2, 2, 1)
            # 结束检测二维码的线程
            if self.qrcode_check_thread:
                self.qrcode_check_thread.stop_thread()
            else:
                pass
            # 清理图片缓存
            for index in range(1, 3):
                if os.path.isfile(self.qrcode_image_path[index - 1]):
                    os.remove(self.qrcode_image_path[index - 1])
            # 接受关闭事件
            event.accept()

    def restore_from_tray(self):
        self.showNormal()
        self.activateWindow()

    def re_start(self):
        if self.restart_flag:
            pass
        else:
            if not self.close:
                # 停止所有相关进程
                self.bot_run_process.stop_process(self.queue_2, 1, 1)
                self.bot_run_process.stop_process(self.queue_2, 2, 1)
                # 结束检测二维码的线程
                if self.qrcode_check_thread:
                    self.qrcode_check_thread.stop_thread()
                else:
                    pass
                # 清理图片缓存
                for index in range(1, 3):
                    if os.path.isfile(self.qrcode_image_path[index - 1]):
                        os.remove(self.qrcode_image_path[index - 1])
                _title = "登录出错"
                _content = "检测到掉线，应用将重新启动，请重新扫码登录"
                msg_box = Dialog(_title, _content)
                msg_box.yesButton.setText("确认")
                msg_box.cancelButton.hide()
                msg_box.buttonLayout.insertStretch(1)
                if msg_box.exec():
                    self.restart_application()
                else:
                    pass
            else:
                pass

    def restart_application(self):
        os.execv(sys.executable, ['python'] + sys.argv)

    def setupLogUpdater(self):
        # 设置定时器来定期读取日志文件
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.updateLogViewer)
        self.timer.start(1000)  # 每1000毫秒（即1秒）触发一次

        self.last_position_1 = 0  # 记录上次读取的位置
        self.last_position_2 = 0

    def updateLogViewer(self):
        # 实时更新日志显示
        try:
            # 检查 bot1 日志文件大小
            file_size_1 = os.path.getsize("bots/bot1/run_1.log")
            if file_size_1 == 0:
                self.ui.logViewer_1.clear()
                self.last_position_1 = 0  # 重置读取位置

            with open("bots/bot1/run_1.log", "r", encoding='utf-8') as logFile_1:
                logFile_1.seek(self.last_position_1)  # 移动到上次读取的位置
                new_text = logFile_1.read()  # 读取新内容
                if new_text:  # 如果有新内容，更新界面
                    self.ui.logViewer_1.appendPlainText(new_text)
                    self.last_position_1 = logFile_1.tell()  # 更新读取位置

            # 检查 bot2 日志文件大小
            file_size_2 = os.path.getsize("bots/bot2/run_2.log")
            if file_size_2 == 0:
                self.ui.logViewer_2.clear()
                self.last_position_2 = 0  # 重置读取位置

            with open("bots/bot2/run_2.log", "r", encoding='utf-8') as logFile_2:
                logFile_2.seek(self.last_position_2)  # 移动到上次读取的位置
                new_text = logFile_2.read()  # 读取新内容
                if new_text:  # 如果有新内容，更新界面
                    self.ui.logViewer_2.appendPlainText(new_text)
                    self.last_position_2 = logFile_2.tell()  # 更新读取位置
        except Exception as e:
            logger.info(f"更新日志出错: {e}")

    def check_for_updates(self, flag=0):
        """检查是否有更新"""
        update_info = fetch_update_info()
        if update_info["version"] > CURRENT_VERSION_NUMBER:
            _title = "新版本已就绪"
            _content = f"新版本 （{update_info['version']}） 已就绪.\n{update_info['description']}\n是否现在下载更新?"
            msg_box = Dialog(_title, _content)
            msg_box.yesButton.setText("确认")
            msg_box.cancelButton.setText("稍后")

            if msg_box.exec():
                try:
                    # 创建并显示进度条对话框
                    self.progress_dialog = ProgressDialog(self)
                    self.progress_dialog.show()

                    # 创建并启动下载线程
                    self.download_thread = DownloadThread(update_info["download_url"], update_info["checksum"],
                                                          self.progress_dialog.progress_signal,
                                                          self.progress_dialog.complete_signal)
                    self.download_thread.daemon = True
                    self.download_thread.start()
                except Exception as e:
                    QMessageBox.critical(None, "更新失败", str(e))
            else:
                pass

        else:
            if flag == 0:
                _content = f"当前版本 （{update_info['version']}）已是最新版本"
                msg_box = Dialog("已是最新版本", _content)
                msg_box.yesButton.setText("确认")
                msg_box.cancelButton.hide()
                msg_box.buttonLayout.insertStretch(1)
                if msg_box.exec():
                    pass
                else:
                    pass
            else:
                pass

def fetch_update_info():
    """从服务器获取更新信息"""
    url = "https://qn.aicache.wooxin.cn/client/update_information{}.json".format(VERSION)
    try:
        response = requests.get(url, verify=False)
    except:
        _title = "检测更新失败"
        _content = "网络环境异常，如有代理请关闭代理"
        msg_box = Dialog(_title, _content)
        msg_box.yesButton.setText("确认")
        msg_box.cancelButton.hide()
        msg_box.buttonLayout.insertStretch(1)
        if msg_box.exec():
            pass
        else:
            pass
    return response.json()


def verify_checksum(file_path, expected_checksum):
    """验证文件的SHA256校验和"""
    hasher = hashlib.sha256()
    with open(file_path, 'rb') as f:
        buf = f.read()
        hasher.update(buf)
    return hasher.hexdigest() == expected_checksum


def replace_and_restart(temp_file, win, app):
    # 获取当前运行的EXE文件的完整路径
    current_exe_path = sys.executable
    exe_dir = os.path.dirname(current_exe_path)
    exe_name = os.path.basename(current_exe_path)

    # 新EXE文件的名称和路径
    new_exe_name = "UserCareSystem{}.exe".format(VERSION)
    new_exe_path = os.path.join(exe_dir, new_exe_name)

    # 替换旧的EXE文件
    try:
        # 先备份旧的EXE文件
        backup_path = os.path.join(exe_dir, "旧版本_" + exe_name)
        shutil.move(current_exe_path, backup_path)

        # 移动新文件到正确的位置
        shutil.move(temp_file, new_exe_path)

        try:
            win.close_process()
            app.quit()
        except:
            pass

        # 重启应用程序
        os.execv(new_exe_path, ['python'] + sys.argv + ['--create-shortcut'])
    except Exception as e:
        # 如果替换失败，恢复旧的EXE文件
        shutil.move(backup_path, current_exe_path)
        logger.info("更新发生错误：{}".format(e))



class DownloadThread(threading.Thread):
    def __init__(self, download_url, checksum, progress_signal, complete_signal):
        super().__init__()
        self.download_url = download_url
        self.checksum = checksum
        self.progress_signal = progress_signal
        self.complete_signal = complete_signal
        self.temp_file = None

    def run(self):
        # 获取当前运行的EXE文件的完整路径
        current_exe_path = sys.executable
        exe_dir = os.path.dirname(current_exe_path)
        exe_name = os.path.basename(current_exe_path)

        # 新EXE文件的名称和路径
        new_exe_name = "UserCareSystem{}.exe".format(VERSION)
        new_exe_path = os.path.join(exe_dir, new_exe_name)

        # 下载新EXE文件到临时位置
        temp_file = os.path.join(exe_dir, "temp_" + new_exe_name)

        try:
            response = requests.get(self.download_url, stream=True, verify=False)
            response.raise_for_status()

            total_size = int(response.headers.get('content-length', 0))
            with open(temp_file, 'wb') as file:
                for chunk in response.iter_content(chunk_size=8192):
                    file.write(chunk)
                    progress = int(100 * file.tell() / total_size)
                    self.progress_signal.emit(progress)

            if not verify_checksum(temp_file, self.checksum):
                raise ValueError("检验校验和失败，文件未完全下载，请稍后重试")

            self.temp_file = temp_file

        except Exception as e:
            raise e

        self.complete_signal.emit(self.temp_file, None)

def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

def create_desktop_shortcut():
    try:
        # 获取当前脚本的绝对路径
        script_path = os.path.abspath(sys.argv[0])

        # 获取桌面路径
        desktop_path = os.path.join(os.environ['USERPROFILE'], 'Desktop')

        # 快捷方式文件的名称
        shortcut_name = "UserCareSystem.lnk"
        shortcut_path = os.path.join(desktop_path, shortcut_name)

        # 检查并删除已存在的以“UserCareSystem”开头的快捷方式
        for file_name in os.listdir(desktop_path):
            if file_name.startswith("UserCareSystem") and file_name.endswith(".lnk"):
                file_path = os.path.join(desktop_path, file_name)
                os.remove(file_path)

        # 创建Shell对象
        shell = win32com.client.Dispatch('WScript.Shell')

        # 创建快捷方式
        shortcut = shell.CreateShortcut(shortcut_path)
        shortcut.TargetPath = script_path
        shortcut.WorkingDirectory = os.path.dirname(script_path)
        shortcut.IconLocation = f"{script_path}, 0"
        shortcut.Save()
    except:
        pass

def clear_log_file(file_path):
    try:
        if os.path.exists(file_path):
            with open(file_path, 'w') as f:
                f.truncate(0)  # 清空文件内容
    except Exception as e:
        pass


def clear_logs():
    try:
        threads = []

        # 主日志文件
        file_path = "run.log"
        thread = threading.Thread(target=clear_log_file, args=(file_path,))
        thread.daemon = True
        threads.append(thread)
        thread.start()

        # 子日志文件
        for i in range(1, 3):
            file_path = f"bots/bot{i}/run_{i}.log"
            thread = threading.Thread(target=clear_log_file, args=(file_path,))
            thread.daemon = True
            threads.append(thread)
            thread.start()
    except:
        pass


def delete_old_version_exes():
    try:
        current_script_name = os.path.basename(sys.argv[0])

        for filename in os.listdir('.'):
            if filename.startswith('旧版本') and filename.endswith('.exe'):
                if filename != current_script_name:
                    try:
                        os.remove(filename)
                        logger.info(f"已删除文件: {filename}")
                    except Exception as e:
                        logger.info(f"删除文件 {filename} 时出错: {e}")
    except:
        pass


def get_mac_address():
    mac_num = hex(uuid.getnode()).replace('0x', '').upper()
    mac_address = ':'.join(mac_num[i:i + 2] for i in range(0, 12, 2))
    logger_1.info("本机MAC地址为：{}".format(mac_address))
    return mac_address

def main_is_admin():
    if not is_admin():
        # 重新启动程序并请求管理员权限
        ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
    else:
        if __name__ == "__main__":
            multiprocessing.freeze_support()

            delete_old_version_exes()

            # 检查命令行参数，如果包含 --create-shortcut，则不创建快捷方式
            if '--create-shortcut' in sys.argv:
                pass
            elif not sys.argv[1:]:
                create_desktop_shortcut()

            App = SingleInstance("UseCareSystem")

            translator = FluentTranslator()
            App.installTranslator(translator)

            # 设置字体
            font = QFont()
            font.setFamily('Microsoft YaHei')
            App.setFont(font)

            win = MainWindow()
            dialog_config.win = win
            dialog_advanced_config.win = win
            ui_friend_list.win = win
            progress_dialog.win = win
            progress_dialog.App = App
            win.show()

            # 检查更新
            try:
                win.check_for_updates(1)
            except:
                pass

            try:
                get_mac_address()
            except:
                pass

            sys.exit(App.exec_())

def main():
    multiprocessing.freeze_support()

    delete_old_version_exes()

    # 检查命令行参数，如果包含 --create-shortcut，则不创建快捷方式
    if '--create-shortcut' in sys.argv:
        pass
    elif not sys.argv[1:]:
        create_desktop_shortcut()

    App = SingleInstance("UseCareSystem")

    translator = FluentTranslator()
    App.installTranslator(translator)

    # 设置字体
    font = QFont()
    font.setFamily('Microsoft YaHei')
    App.setFont(font)

    win = MainWindow()
    dialog_config.win = win
    dialog_advanced_config.win = win
    ui_friend_list.win = win
    progress_dialog.win = win
    progress_dialog.App = App
    win.show()

    # 检查更新
    try:
        win.check_for_updates(1)
    except:
        pass

    try:
        get_mac_address()
    except:
        pass

    sys.exit(App.exec_())


if __name__ == "__main__":
    # main()
    main_is_admin()
